package com.weilai.controller.exceptionHandler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    // 处理业务异常
    @ExceptionHandler(BusinessException.class)
    public ModelAndView handleBusinessException(BusinessException ex,
                                                HttpServletRequest request,
                                                RedirectAttributes redirectAttributes) {
        //方便记录具体异常信息，项目上线时最好删除
        ex.printStackTrace();
        // 记录警告日志（业务异常通常不需要记录错误级别）
        logger.warn("业务异常 [code={}, path={}] {}",
                ex.getErrorCode(),
                request.getRequestURI(),
                ex.getMessage());

        // 设置重定向属性
        redirectAttributes.addFlashAttribute("errorCode", ex.getErrorCode());
        redirectAttributes.addFlashAttribute("errorMessage", ex.getErrorMessage());

        // 获取来源页面并处理空指针
        String referer = getSafeReferer(request);
        return new ModelAndView("redirect:" + referer);
    }

    // 处理系统异常
    @ExceptionHandler(SystemException.class)
    public ModelAndView handleSystemException(SystemException ex,
                                              HttpServletRequest request,
                                              RedirectAttributes redirectAttributes) {
        //方便记录具体异常信息，项目上线时最好删除
        ex.printStackTrace();
        // 记录错误日志（包含异常堆栈）
        logger.error("系统异常 [code={}, path={}]",
                ex.getErrorCode(),
                request.getRequestURI(),
                ex);

        // 设置重定向属性
        redirectAttributes.addFlashAttribute("errorCode", ex.getErrorCode());
        redirectAttributes.addFlashAttribute("errorMessage", "系统繁忙，请稍后再试");

        String referer = getSafeReferer(request);
        return new ModelAndView("redirect:" + referer);
    }

    // 处理参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ModelAndView handleValidationException(MethodArgumentNotValidException ex,
                                                  HttpServletRequest request,
                                                  RedirectAttributes redirectAttributes) {
        BindingResult result = ex.getBindingResult();
        List<String> errors = result.getFieldErrors().stream()
                .map(f -> f.getField() + ": " + f.getDefaultMessage())
                .collect(Collectors.toList());

        //方便记录具体异常信息，项目上线时最好删除
        ex.printStackTrace();
        // 记录校验失败详情
        logger.info("参数校验失败 [path={}] {}", request.getRequestURI(), errors);

        redirectAttributes.addFlashAttribute("errors", errors);
        redirectAttributes.addFlashAttribute("errorCode", Code.PROJECT_VALIDATE_ERROR);

        String referer = getSafeReferer(request);
        return new ModelAndView("redirect:" + referer);
    }

    // 处理404异常
    @ExceptionHandler(NoHandlerFoundException.class)
    public ModelAndView handleNotFound(NoHandlerFoundException ex,
                                       HttpServletRequest request,
                                       RedirectAttributes redirectAttributes) {
        //方便记录具体异常信息，项目上线时最好删除
        ex.printStackTrace();
        logger.warn("404异常 [method={}, path={}]",
                ex.getHttpMethod(),
                ex.getRequestURL());

        redirectAttributes.addFlashAttribute("errorCode", Code.PROJECT_DATA_NOT_FOUND);
        redirectAttributes.addFlashAttribute("errorMessage", "请求的资源不存在");

        // 如果404页面是API请求，可以重定向到首页
        return new ModelAndView("redirect:/");
    }

    // 处理全局未分类异常
    @ExceptionHandler(Exception.class)
    public ModelAndView handleGlobalException(Exception ex,
                                              HttpServletRequest request,
                                              RedirectAttributes redirectAttributes) {
        //方便记录具体异常信息，项目上线时最好删除
        ex.printStackTrace();
        // 特殊异常处理
        if (ex instanceof NullPointerException) {
            logger.error("空指针异常 [path={}]", request.getRequestURI(), ex);
            redirectAttributes.addFlashAttribute("errorCode", Code.SYSTEM_UNKNOWN_ERROR);
            redirectAttributes.addFlashAttribute("errorMessage", "系统内部错误");
        } else if (ex instanceof IllegalArgumentException) {
            logger.warn("非法参数异常 [path={}] {}", request.getRequestURI(), ex.getMessage());
            redirectAttributes.addFlashAttribute("errorCode", Code.PROJECT_VALIDATE_ERROR);
            redirectAttributes.addFlashAttribute("errorMessage", ex.getMessage());
        } else {
            logger.error("未捕获的异常 [path={}]", request.getRequestURI(), ex);
            redirectAttributes.addFlashAttribute("errorCode", Code.SYSTEM_UNKNOWN_ERROR);
            redirectAttributes.addFlashAttribute("errorMessage", "系统繁忙，请稍后重试");
        }

        String referer = getSafeReferer(request);
        return new ModelAndView("redirect:" + referer);
    }

    // 安全获取Referer地址
    private String getSafeReferer(HttpServletRequest request) {
        String referer = request.getHeader("Referer");
        if (referer == null || referer.isEmpty()) {
            // 默认回退到应用根路径
            return request.getContextPath() + "/";
        }
        return referer;
    }
}